<template>
	<view>
		<template v-if="!readonly">
			<view v-if="formProps.expanding && dataOptions.length === 0" style="color:#E79467;">
				{{ $t('webAuto.NoOptionsAvailable') }}</view>

			<!-- 多选 -->
			<template v-else-if="formProps.multiple">
				<uni-data-checkbox v-if="formProps.expanding" :map="optionsKeyMap" multiple v-model="__value"
					:localdata="dataOptions" />
				<multiple-picker v-slot="{ show }" v-else index="name" v-model="__value" :options="dataOptions">
					<click-input :value="selectVal"
						:placeholder="formProps.placeholder ? $t(formProps.placeholder) : $t('webAuto.PleaseSelect')"
					@click="show" />
				</multiple-picker>
			</template>

			<!-- 单选 -->
			<template v-else>
				<uni-data-checkbox v-if="formProps.expanding" :map="optionsKeyMap" v-model="__value"
					:localdata="dataOptions" />
				<picker v-else @change="ok" mode="selector" :value="index" range-key="name" :range="dataOptions">
					<click-input :value="(modelValue || []).length > 0 ? dataOptions[index] : null" index="name"
						:placeholder="formProps.placeholder ? $t(formProps.placeholder) : $t('webAuto.PleaseSelect')" />
				</picker>
			</template>
		</template>
		<!-- 只读模式 -->
		<template v-else>
			<click-input disabled v-if="formProps.multiple"
				:value="(modelValue || []).length > 0 ? dataOptions[index] : null" index="name" />
			<click-input disabled v-else :value="selectVal" />
		</template>
	</view>
</template>

<script setup>
import { watch,computed, onMounted, ref } from 'vue'
import { $nEmpty } from '@/utils/tool.js'
import ClickInput from '@/components/ClickInput.vue'
import MultiplePicker from '@/components/common/MultiplePicker.vue'
// #ifndef H5
import { Function } from "eval5";
// #endif
import { useI18n } from 'vue-i18n';

const { t } = useI18n();
const props = defineProps({
	formProps: {
		type: Object,
		default: () => {
			return {}
		}
	},
	modelValue: {
		type: Array,
		default: () => {
			return []
		}
	},
  formData: {
    type: Object,
    default: () => {
      return {}
    }
  },
	readonly: Boolean
})

const _value = computed({
	get() {
		return props.modelValue || []
	},
	set(val) {
		emits('update:modelValue', val)
	}
})

const selectVal = computed(() => {
	return dataOptions.value.filter(v => (props.modelValue || []).indexOf(v.value) > -1).map(v => v.name)
})

const __value = computed({
	get() {
		return props.formProps.multiple ? _value.value : _value.value[0]
	},
	set(val) {
		if (props.formProps.multiple) {
			emits('update:modelValue', val)
		} else {
			emits('update:modelValue', [val])
		}
	}
})

const emits = defineEmits(['update:modelValue'])

const loading = ref(false)
const dataOptions = ref([])
let preHandlerFuc = null
let aftHandlerFuc = null
const optionsKeyMap = { text: 'name', value: 'value' }
const index = ref(0)

function loadOptionsData() {
	try {
		if (props.formProps.fixed) {
			// 翻译
			props.formProps.options.forEach(item=>{
				item.name=t(item.name)
			})
			dataOptions.value = props.formProps.options
		} else {
			doRequest(dataOptions.value)
		}
	} catch (e) {
		console.log(e)
	}
}

onMounted(() => {
	loadOptionsData()
})

//监听表单值变化
watch(() => props.formData,
    (newVal) => {
      loadOptionsData()
    },
    { deep: true }
)

function ok(e) {
	index.value = e.detail.value
	__value.value = dataOptions.value[index.value].value
}

function doRequest(options) {
	const http = props.formProps.http || {}
	if (http.url && http.method) {
		const params = {
			url: http.url,
			method: http.method,
			headers: {
				'content-type': http.contentType === 'JSON' ? 'application/json' :
					'application/x-www-form-urlencoded',
				...coverParams(http.headers || [])
			},
			params: {},
			data: http.contentType === 'JSON' ? JSON.parse(http.data || '{}') : coverParams(http.params || []),
		}
		preHandler(params, http.preHandler)
		if (http.contentType !== 'JSON') {
			params.data = { ...params.data, ...params.params }
		}
		loading.value = true
		uni.request({
			...params,
			timeout: 20000,
			header: params.headers,
			dataType: 'json',
			success: (rsp) => {
				loading.value = false
				const ops = aftHandler(rsp, http.aftHandler)
				options.length = 0
				options.push(...(ops || []))
			},
			fail: (err) => {
				loading.value = false
				uni.showToast({
					icon: 'none',
					title: '请求http数据源发生异常:' + JSON.stringify(err)
				})
			}
		})
	}
}
//数组转对象
function coverParams(args, isForm = false) {
	// const params = {};
	// if (Array.isArray(args)) {
	// 	args.forEach(arg => {
	// 		if ($nEmpty(arg.name)) {
	// 			params[arg.name] = arg.value
	// 		}
	// 	})
	// }
	// return params
	const params = {};
	if (Array.isArray(args)) {
		args.forEach(arg => {
			if ($nEmpty(arg.name)) {
				params[arg.name] = arg.value.replace(/\$\{(\w+)\}/g, (match, key) => {
					return props.formData[key] || '';
				})
			}
		})
	} else {
		params = { ...args }
	}
	if (isForm) {
		return Object.keys(params).map(v => `${v}=${params[v]}`).join('&')
	}
	return params
}

//前置处理
function preHandler(params, script) {
	if (script) {
		if (!preHandlerFuc) {
			// #ifndef MP-WEIXIN
			preHandlerFuc = new Function('ctx', `${script}\n preHandler(ctx)`)
			// #endif
			// #ifdef MP-WEIXIN
			preHandlerFuc = () => { }
			// #endif
		}
		try {
			preHandlerFuc(params)
		} catch (e) {
			console.log(e)
		}
	}
}

//后置处理
function aftHandler(rsp, aftHandler) {
	if (typeof (aftHandler) === 'string') {
		return toFunc(rsp, aftHandler)
	} else {
		//新格式，带字段设置
		if (aftHandler.isJs) {
			return toFunc(rsp, aftHandler.js)
		} else {
			//取值进行转，拿到数组
			const dataArr = getData(rsp, ifEmGet(aftHandler.rule.source, 'data'));
			const name = ifEmGet(aftHandler.rule.name, 'name')
			const value = ifEmGet(aftHandler.rule.value, 'value')
			return (dataArr || []).map(v => {
				return {
					name: v[name],
					value: v[value],
				}
			})
		}
	}
}

function ifEmGet(v, dv) {
	return $nEmpty(v) ? v : dv
}

function getData(obj, path) {
	// 将路径字符串分割成数组
	const keys = path.split('.');
	// 初始化结果为传入的对象
	let result = obj;
	// 逐层查找属性值
	for (const key of keys) {
		if (result.hasOwnProperty(key)) {
			result = result[key];
		} else {
			return undefined;
		}
	}
	return result;
}

function toFunc(rsp, script) {
	if (script) {
		if (!aftHandlerFuc) {
			// #ifndef MP-WEIXIN
			aftHandlerFuc = new Function('rsp', `${script}\n return aftHandler(rsp)`)
			// #endif
			// #ifdef MP-WEIXIN
			aftHandlerFuc = () => { }
			// #endif
		}
		try {
			return aftHandlerFuc(rsp) || []
		} catch (e) {
			console.log(e)
		}
	}
	return []
}
</script>

<style></style>
